package hu.myai.controller;

import hu.myai.model.db.AxHistory;
import hu.myai.util.DatabaseUtil;
import hu.myai.util.WebNoCookies;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.StringTokenizer;

import javax.persistence.EntityTransaction;

import org.joone.log.ILogger;
import org.joone.log.LoggerFactory;

public class SaveHistoryYahoo {

	private static final ILogger log = LoggerFactory.getLogger(SaveHistoryYahoo.class);

	WebNoCookies webNoCookies = null;

	// for database util reference
	private DatabaseUtil dbUtil = new DatabaseUtil();

	public SaveHistoryYahoo() {
	}

	protected boolean getYahooCompanyList(Date startDate, Date endDate) {

		log.info("Get Yahoo company list");

		WebNoCookies webNoCookies = new WebNoCookies();

		try {
			String myUrl = new String("http://www.asx.com.au/asx/downloadCsv/ASXListedCompanies.csv");

			// read date from web
			InputStream rawInStream = webNoCookies.getURLGetString(new URL(myUrl));

			/** Error handling: not data was read */
			if (rawInStream == null) {
				return false;
			}

			BufferedReader response = new BufferedReader(new InputStreamReader(rawInStream));

			String line = null;
			// remove the heather
			for (int i = 0; i < 4; i++)
				line = response.readLine();
			// Start EntityManagerFactory

			int i = 1;
			// store in db
			while (line != null && !line.equals("") && line.indexOf(",") != -1) {

				StringTokenizer tokens = new StringTokenizer(line, ",\n");
				if (tokens.countTokens() >= 2) {

					String companyName = tokens.nextToken();
					String symbol = tokens.nextToken();
					String group = tokens.nextToken();

					/** check whatever is in the symbol list */
					// if (Constans.forCheckSymbol.indexOf(symbol) != -1) {
					/** check if it is a ordinary stock or not */
					if (symbol.length() == 3) {

						getYahooHistory(startDate, endDate, symbol);
						i++;
					}
				}
				line = response.readLine();
			}

			response.close();

			log.info("Get Sanford data end.");

		} catch (IOException ex) {
			// Use Log4j
			log.error("IOException thrown while initializing the Yahoo. Message is : " + ex.getMessage()); // LOG4J
			ex.printStackTrace();
			return false;
		} catch (Exception ex) {
			// Use Log4j
			log.error("Exception thrown while initializing the Yahoo. Message is : " + ex.getMessage()); // LOG4J
			ex.printStackTrace();
			return false;
		}

		dbUtil.entityManager.clear();

		log.info("Get Sanford data end.");
		return true;

	} // End method initInputStream

	protected boolean getYahooHistory(Date startDate, Date endDate, String symbol) {

		log.info("Get Sanford symbol for: " + symbol);

		SimpleDateFormat formatter;

		EntityTransaction tx = dbUtil.entityManager.getTransaction();
		tx.begin();

		String line = "", myUrl = "";

		WebNoCookies webNoCookies = new WebNoCookies();

		Calendar startCal = Calendar.getInstance();
		startCal.setTime(startDate);

		Calendar endCal = Calendar.getInstance();
		endCal.setTime(endDate);

		try {
			myUrl = new String("http://ichart.finance.yahoo.com/table.csv?" + "s=" + symbol + ".AX&a="
					+ startCal.get(Calendar.MONTH) + "&b=" + startCal.get(Calendar.DATE) + "&c="
					+ startCal.get(Calendar.YEAR) + "&d=" + endCal.get(Calendar.MONTH) + "&e="
					+ endCal.get(Calendar.DATE) + "&f=" + startCal.get(Calendar.YEAR) + "&g=d&ignore=.csv");

			// read date from web
			InputStream rawInStream = webNoCookies.getURLGetString(new URL(myUrl));

			/** Error handling: not data was read */
			if (rawInStream == null) {
				tx.rollback();
				return false;
			}
			BufferedReader response = new BufferedReader(new InputStreamReader(rawInStream));

			/** Skipp the header */
			for (int i = 0; i < 2; i++)
				line = response.readLine();

			int i = 1;
			List<String> recordList = new ArrayList<String>();

			/** makes reverse order */
			while (line != null && !line.equals("") && line.indexOf(",") != -1) {
				recordList.add(0, line);
				line = response.readLine();
			}
			response.close();

			/** store records to the database */
			for (String recLine : recordList) {
				line = recLine;
				StringTokenizer tokens = new StringTokenizer(line, ",\n");
				if (tokens.countTokens() >= 5) {

					/** check whatever is in the symbol list */
					// if (Constans.forCheckSymbol.indexOf(symbol) != -1) {
					/** check if it is a ordinary stock or not */
					formatter = new SimpleDateFormat("yyyy-MM-dd");
					Date date = formatter.parse(tokens.nextToken());

					// get saved record
					AxHistory history = dbUtil.getSavedHistory(date, symbol);

					if (history != null) {
						log.debug("It is skipped: " + symbol + "  " + date);
						continue;
					}

					history = new AxHistory();

					history.setSymbol(symbol);
					history.setDate(date);

					Double open = new Double(tokens.nextToken());
					Double high = new Double(tokens.nextToken());
					Double low = new Double(tokens.nextToken());
					Double close = new Double(tokens.nextToken());
					Integer volume = new Integer(tokens.nextToken());

					if (open == 0.0 && close == 0.0 && high == 0.0 && low == 0.0 && volume == 0) {
						log.error("Error - not valid record from Yahoo: " + symbol + ", " + date);
						// cannot loose this information
						// continue;
					}

					// consolidate the result
					if (open == 0.0)
						open = close != 0.0 ? close : (high != 0.0 ? high : low);
					if (high == 0.0)
						high = close != 0.0 ? close : (open != 0.0 ? open : low);
					if (low == 0.0)
						low = close != 0.0 ? close : (high != 0.0 ? high : open);
					if (close == 0.0)
						close = low != 0.0 ? low : (high != 0.0 ? high : open);

					history.setOpen(open);
					history.setHigh(high);
					history.setLow(low);
					history.setClose(close);
					history.setVolume(volume);

					// get and set the parent of this record
					AxHistory lastRecord = dbUtil.getLastHistory(date, symbol);
					history.setParent(lastRecord);

					dbUtil.entityManager.persist(history);
					log.debug("It is done: " + symbol + "  " + date);
					if (i % 40 == 0) {
						tx.commit();
						tx.begin();
						log.debug("Commit...");
					}
					i++;
				}
			}

			tx.commit();
			dbUtil.entityManager.clear();

			log.debug("It is done: " + symbol);

		} catch (IOException ex) {
			// Use Log4j
			log.error("IOException thrown while initializing the Yahoo. Message is : " + ex.getMessage()); // LOG4J
			tx.rollback();
			return false;
		} catch (Exception ex) {
			// Use Log4j
			log.error("Exception thrown while initializing the Yahoo. Message is : " + ex.getMessage()); // LOG4J
			tx.rollback();
			return false;
		}

		return true;
	}
}
